package com.cars.theadpool.config;

import com.cars.theadpool.executor.VisibleThreadPoolTaskExecutor;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author: caoqianfan
 * @date: 2023/11/13 9:35
 */
@Configuration
@EnableAsync
@Data
public class ExecutorConfig {

    /**
     * 线程池中的核心线程数量,默认为1
     */
    @Value("${async.executor.thread.core_pool_size}")
    private int corePoolSize;

    /**
     * 线程池中的最大线程数量
     */
    @Value("${async.executor.thread.max_pool_size}")
    private int maxPoolSize;

    /**
     * 线程池中允许线程的空闲时间,默认为 60s
     */
    @Value("${async.executor.thread.keep_alive_time}")
    private int keepAliveTime;

    /**
     * 线程池中的队列最大数量
     */
    @Value("${async.executor.thread.queue_capacity}")
    private int queueCapacity;

    /**
     * 线程的名称前缀
     */
    @Value("${async.executor.thread.name.prefix}")
    private String namePrefix;

    /**
     * <b>线程池的参数说明</b>：<br>
     * <font color ="yellow">corePoolSize</font>-核心线程数<br>
     * <font color ="yellow">maximumPoolSize</font>-最大线程数<br>
     * <font color ="yellow">keepAliveTime</font>-最大空闲时间<br>
     * <font color ="yellow">unit</font>-最大空闲时间单位<br>
     * <font color ="yellow">workQueue</font>-任务队列<br>
     * <font color ="yellow">handler</font>-拒绝策略，有以下四种<br>
     * （1）<font color ="red">ThreadPoolExecutor.AbortPolicy</font>-丢弃任务，并抛出 RejectedExecutionException 异常。<br>
     * （2）<font color ="red">ThreadPoolExecutor.CallerRunsPolicy</font>-该任务被线程池拒绝，由调用 execute方法的线程执行该任务。<br>
     * （3）<font color ="red">ThreadPoolExecutor.DiscardOldestPolicy</font>- 抛弃队列最前面的任务，然后重新尝试执行任务。<br>
     * （4）<font color ="red">ThreadPoolExecutor.DiscardPolicy</font>-丢弃任务，不过也不抛出异常。<br>
     * 也可以自己实现<b>RejectedExecutionHandler</b>接口来自定义拒绝策略。<br>
     *
     * @return {@code ThreadPoolTaskExecutor}
     */
    @Bean(name = "asyncServiceExecutor")
    public ThreadPoolTaskExecutor asyncServiceExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
        threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveTime);
        threadPoolTaskExecutor.setThreadNamePrefix(namePrefix);
        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
        // CALLER_RUNS：不在新线程中执行任务，而是由调用者所在的线程来执行
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //加载
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    /**
     * 打印线程池情况
     *
     * @return {@code Executor}
     */
    @Bean("visibleTaskExecutor")
    public Executor visible() {
        //1、使用VisibleThreadPoolTaskExecutor作为类
        ThreadPoolTaskExecutor executor = new VisibleThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveTime);
        executor.setThreadNamePrefix(namePrefix);
        //设置线程池关闭的时候 等待所有的任务完成后再继续销毁其他的bean
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}